Auto merge of #2821 - bennofs:no-transitive-dep-feature, r=alexcrichton
authorbors <bors@rust-lang.org>
Sun, 3 Jul 2016 17:29:07 +0000 (10:29 -0700)
committerGitHub <noreply@github.com>
Sun, 3 Jul 2016 17:29:07 +0000 (10:29 -0700)
commit3fcbb108400aa1fc6321c8e166d81188debaf0bc
tree744d706aacee566824a2ff8818d300f149d98f19
parent5716f32d78b1baf629e055573a682a6730936b4b
parent848f8b5955dcc9b5c3d256cd5b6d891052075556
Auto merge of #2821 - bennofs:no-transitive-dep-feature, r=alexcrichton

Disallow specifying features of transitive deps

Before this commit, it was possible to activate a feature in a transtive
dependency, using a Cargo.toml like the following one:

    ...
    [features]
    # this will enable feature fast in package bar, which is a
    # dependency of foo
    default = [ foo/bar/fast ]

This is a bug, and was never intended, and it is checked in other places
already. The behavior was possible because `build_features::add_feature`
treats the specification "foo/bar/fast" as just another feature. So when
we require the feature "foo/bar/fast", add_feature for foo will generate a
dependency on "foo" requiring that feature "bar/fast" is enabled. Then,
when resolving foo, add_feature will find that "bar/fast" is a required
feature, so it'll happily add "fast" as the required feature for the
dependency "foo".

The fix for this is to make sure that the `add_feature` function does
not treat `a/b` specifications as just another feature. Instead, it now
handles that case without recursion directly when it encounters it.

We can see how this resolves the above problem: when resolving foo,
add_feature for the required feature "bar/fast" will be called.
Because add_feature no longer treats such specifciations differently at
the top level, it will try to enable a feature with the exact name
"bar/fast", and Context::resolve_features will later find that no such
feature exists for package foo.

To give a friendlier error message, we also check in
Context::resolve_features that we never ever require a feature with a
slash in a name from a dependency.